(function(){
    "use strict";

    angular.module('zhxNextPage',[]);
    /**
     * ZHX-NEXT-PAGE 指令
     *
     * @Author          Vicco Wang
     * @createdDate     2016-07-28
     *
     * @lastModified    2016-07-29
     *
     * 说明:
     *
     * 该指令不依赖于任何其他组件，但仅能应用于zhx-tab-frame框架之下。
     * 该指令的目的是为了在一个标签页(tab)下，打开多个层级页面(比如三级下一步或更多层级页面).
     * 该指令并无限制层级。在任意层级页面的控制器中均可使用，使用后将会创建一个下一级页面。
     *
     *
     * 如何使用:
     *
     * 1) 项目中的模块依赖注入 [ zhxNextPage ] 模块
     *
     * 2) 在你的控制器中需要注入 [ nextPageService ] 服务
     *
     * 3) 在控制器中如下使用：
     *
     * @param   templateUrl       模板的URL相对路径
     * @param   scope             模板需要的scope作用域，这里一般默认传递当前作用域给模板
     * @param   controller        模板需要的控制器，这里可以填控制器名称，也可以直接写控制器方法
     * @return  openPromise       返回promise对象，可以用来执行嵌套页面打开后的回调方法,回调接收到一个对象param，
     *                              对象中包含:
     *                              [pageElement]   嵌套页面的HTML对象(AngularJS封装后的)
     *                              [pageScope]     嵌套页面的scope
     *                              [statusText]    嵌套页成功打开后返回的一个字符串
     *
     * 例子：
     *
     * nextPageService.open({
     *      templateUrl : 'someTemplate.html',
     *      scope : $scope,
     *      controller : 'templateController'
     * })
     * .then(function(res){
     *      //do sth after page opened
     * })
     *
     * 关闭当前页面：
     *
     * nextPageService.close($scope);    关闭当前页面，并将当前页面的作用域作为参数传回父页面;
     *
     *
     * 4) 每次执行后，在任意作用域下均可监听到打开与关闭事件
     *
     * 打开 : zhxNextPage.opened
     * 关闭 : zhxNextPage.closed
     *
     * 例子:
     *
     * $scope.$on('zhxNextPage.opened',function(event,arg){
     *     // 这里[arg]接收到的参数与步骤3中promise接收到的参数一致。
     * });
     * $scope.$on('zhxNextPage.closed',function(event,arg){
     *     // 这里[arg]接收到的参数与步骤3中promise接收到的参数一致。
     * });
     *
     *
     */

    angular.module('zhxNextPage').provider("zhxNextPage", function(){

        var config = {
            //templateUrl : '',
            //scope : {}
        };

        this.config = function(cfg){
            //angular.merge support deep copy!
            config = angular.merge({}, config, cfg);
        };

        this.$get = function() {
            return {
                getConfig : function(){
                    return config;
                }

            }
        }

    });

    angular.module('zhxNextPage').factory('nextPageService',['$rootScope','$q','$http','zhxNextPage','$compile','$controller','$timeout',
                                                            function($rootScope,$q,$http,zhxNextPage,$compile,$controller,$timeout){
        var openPromise = $q.defer(),
            closePromise = $q.defer();

        var privteMethod = {

            newId : function(){
                var date,seed,char,randomChar="",string;
                date = new Date().getTime();
                seed = parseInt( Math.random(1,1000) * 1000 );
                char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
                for( var i = 0 ; i < 5; i++ ){
                    randomChar += char.charAt(Math.floor(Math.random() * 52));
                }
                string = String(seed + date) + randomChar;
                return 'zhxNextPage-' + string.substr(5);
            },

            /**
             * 通过URL读取模板
             * @param tmpl
             * @param config
             * @returns {*}
             */
            loadTemplateUrl : function(tmpl, config) {
                $rootScope.$broadcast('zhxNP.templateLoading', tmpl);
                return $http.get(tmpl, (config || {})).then(function(res) {
                    $rootScope.$broadcast('zhxNP.templateLoaded', tmpl);
                    return res.data || '';
                });
            }

        };

        var publicMethod = {

            open : function(opts){

                var $nextPageId = privteMethod.newId();

                //需要合并默认和用户的配置项
                var options = angular.extend({}, zhxNextPage.getConfig() , opts );

                //该组件必须传递一个scope作用域，否则无法使用
                if(  options.scope == undefined || !options.scope || !angular.isObject(options.scope) ){
                    console.warn("必须传递当前作用域scope");
                    return;
                };

                //模板加载完毕后才进行初始化
                $q.all({
                    template : privteMethod.loadTemplateUrl( options.templateUrl )
                })
                .then(function(res){

                    /**
                     * scope        当前传递进组件的控制器scope
                     * $nextPage    嵌套页对象框架，该框架将加载模板内容，最终插入进VIEW中
                     * $tabPage     当前tab标签页对象，嵌套页必须插入在当前标签页内
                     * tabScope     当前标签页的scope
                     * $template    嵌套页模板，从用户自定义的URL中读取进来的HTML片段
                     * $nextPageArr 嵌套模板的路径数组集合，按照顺序被依次添加至此
                     */
                    var scope, $nextPage, $tabPage, tabScope, $template, $nextPageArr;

                        //创建当前嵌套页scope，该scope继承自用户传进的scope对象。
                        scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
                        //用户传入的模板
                        $template = res.template;

                        //循环获取tab标签页的scope对象
                        //这里用查找是否含有tabId为标准认定该scope为tabScope
                        tabScope = scope;
                        while( tabScope.$parent.tabId !== undefined && tabScope.$parent.tplModule !== undefined ) {
                            tabScope = tabScope.$parent;
                        };

                        //创建层叠页的zIndex级别，默认从20起
                        if( !tabScope.nextPagesIndex ) tabScope.nextPagesIndex = 20;

                        //根据ID来获取当前标签页HTML对象
                        $tabPage = angular.element("." +  tabScope.tabId , "#zhx-tabset-content-main" );

                        $tabPage.css({
                            'position' : 'relative'
                        });

                        //嵌套页对象
                        $nextPage = angular.element("<div id="+ $nextPageId +">"+ $template +"</div>");

                        $nextPage.css({
                            'position' : 'absolute',
                            'width' : '100%',
                            'overflow' : 'auto',
                            'background-color' : '#fff',
                            'top' : 0,left: 0,
                            'z-index' : tabScope.nextPagesIndex++
                        });

                        scope.pageId = $nextPageId;
                        scope.pageElement = $nextPage;
                        scope.tabScope = tabScope;

                        //嵌套页监听标签页关闭的事件
                        //目前什么也不做
                        options.scope.$on("zhxFrame.removed",function(ev,value){
                            //do sth after tab removed.
                        });

                        //为该嵌套页绑定控制器
                        if( options.controller || angular.isArray(options.controller) || angular.isFunction( options.controller ) ){

                            $controller(options.controller,{ $scope : scope, $element : $nextPage});

                        }

                        $timeout(function(){

                            //编译该嵌套页
                            $compile($nextPage)(scope);
                            //插入VIEW
                            $nextPage.appendTo($tabPage);
                            //执行创建成功后的回调，并传递当前scope和嵌套页对象
                            //if( options.opened && angular.isFunction( options.opened ) ){
                            //    //callback()
                            //    options.opened( scope, $nextPage )
                            //};

                            //发送创建成功事件，用户可以在控制器中通过$scope.$on()来实现监听
                            $rootScope.$broadcast("zhxNextPage.opened",scope);

                            openPromise.resolve({
                                pageScope : scope,
                                pageElement : $nextPage,
                                statusText : 'zhxNextPage.opened'
                            });

                        },10);

                });

                return openPromise.promise;

            },

            close : function( scope ){

                if( !scope ){
                    console.warn("关闭层叠页面必须传递当前页scope作用域！");
                    return;
                }

                scope.pageElement.remove();

                $rootScope.$broadcast("zhxNextPage.closed",scope);

                scope.$destroy();

                var closeRes = {
                    status : 'zhxNextPage.closed'
                };

                closePromise.resolve(closeRes);

                return closePromise.promise;

            }
        }

        return publicMethod;

    }])

    angular.module('zhxNextPage').controller('zhxNextPageCtrl',['$scope',function($scope){

    }]);

    angular.module('zhxNextPage').directive('zhxNextPage',['$timeout',function($timeout){
        return {
            restrict : 'E',
            scope : {
                options : '='
            },
            controller : 'zhxNextPageCtrl',
            link : function( scope, tElement, tAttrs, ctrl ){


            }
        }
    }]);

})()

